/**
 * build_project
 * <p>
 * Copyright 2014 cayden.cn, Inc. All rights reserved.
 *
 * @author Administrator
 * @date 2021-06-22 10:17
 */
package com.cayden.config.log;

import java.lang.ClassLoader;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.List;

import ch.qos.logback.classic.LoggerContext;
import com.cayden.config.boot.CaydenBanner;
import com.cayden.config.log.initializer.LogInitializer;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.ILoggerFactory;
import org.slf4j.impl.StaticLoggerBinder;
import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.logback.LogbackLoggingSystem;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.Assert;

/**
 *
 * @author cayden
 * @date 2021-06-22 10:17
 */
@Slf4j
public class CaydenLogbackLoggingSystem extends LogbackLoggingSystem {

    private ClassLoader classLoader;

    public CaydenLogbackLoggingSystem(ClassLoader classLoader){
        super(classLoader);
        this.classLoader = classLoader;
    }

    /**
     * 初始化
     * @param initializationContext
     * @param configLocation
     * @param logFile
     */
    @Override
    public void initialize(
            LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {
        super.initialize(initializationContext, configLocation, logFile);
    }


    @Override
    protected void loadDefaults(LoggingInitializationContext initializationContext, LogFile logFile) {
        LoggerContext context = getLoggerContext();
        context.stop();
        context.reset();
        LogbackConfigurator configurator =
                new LogbackConfigurator(context, this.classLoader, initializationContext.getEnvironment());
        customLog(configurator);
    }

    @Override
    public void cleanUp() {
        super.cleanUp();
    }

    @Override
    public void beforeInitialize() {
        super.beforeInitialize();
    }

    private LoggerContext getLoggerContext() {
        ILoggerFactory factory = StaticLoggerBinder.getSingleton().getLoggerFactory();
        Assert.isInstanceOf(
                LoggerContext.class,
                factory,
                String.format(
                        "LoggerFactory is not a Logback LoggerContext but Logback is on "
                                + "the classpath. Either remove Logback or the competing "
                                + "implementation (%s loaded from %s). If you are using "
                                + "Weblogic you will need to add 'org.slf4j' to "
                                + "prefer-application-packages in WEB-INF/weblogic.xml",
                        factory.getClass(), getLocation(factory)));
        return (LoggerContext) factory;
    }

    private Object getLocation(ILoggerFactory factory) {
        try {
            ProtectionDomain protectionDomain = factory.getClass().getProtectionDomain();
            CodeSource codeSource = protectionDomain.getCodeSource();
            if (codeSource != null) {
                return codeSource.getLocation();
            }
        } catch (SecurityException ex) {
            // Unable to determine location
        }
        return "unknown location";
    }

    private void customLog(LogbackConfigurator configurator) {
        //config log extension
        List<LogInitializer> logInitializers =
                SpringFactoriesLoader.loadFactories(LogInitializer.class, getClassLoader());
        for (LogInitializer logInitializer : logInitializers) {
            logInitializer.init(configurator);
        }
        CaydenBanner.getInfos().addAll(configurator.getLogs());
        log.info("init start");
    }

}
